Skip to content

feat: serialize AgentEvent and StreamDelta for wire transport#72

Merged
yuanhao merged 2 commits into
mainfrom
feat/serialize-agent-events
Jul 14, 2026
Merged

feat: serialize AgentEvent and StreamDelta for wire transport#72
yuanhao merged 2 commits into
mainfrom
feat/serialize-agent-events

Conversation

@yuanhao

@yuanhao yuanhao commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • AgentEvent and StreamDelta now derive Serialize, Deserialize, and PartialEq
  • Wire format: internally tagged camelCase JSON — {"type":"toolExecutionEnd","toolCallId":"...","isError":false} — declared a frozen public contract in the rustdoc and guarded by snapshot tests (all 12 variant tags + camelCase field names)
  • serde floor → 1.0.186 (rename_all_fields; released Aug 2023)
  • Docs: wire-format section on the messages-events page, incl. the lag-resync property (MessageUpdate carries the cumulative message)

This is the only yoagent change needed to support external streaming frontends (websocket fanout, TypeScript clients, JSONL pipes) — first step of the yoyo-serve track.

Additive only: no variant, field, or signature changes; existing sinks that match/clone/Debug events are untouched.

Test plan

  • Round-trip test over one value of every AgentEvent + StreamDelta variant
  • Snapshot: all 12 "type" tags frozen
  • Snapshot: camelCase fields on the wire, snake_case leak asserted absent
  • Unit-variant shape ({"type":"agentStart"}) + inbound raw-JSON parse
  • cargo test --all-features — 393 tests green; clippy -Dwarnings clean

🤖 Generated with Claude Code

yuanhao and others added 2 commits July 14, 2026 03:10
AgentEvent and StreamDelta now derive Serialize, Deserialize, and
PartialEq. The wire format is internally tagged camelCase JSON
({"type":"toolExecutionEnd","toolCallId":...,"isError":false})
and is a frozen public contract guarded by snapshot tests, so external
frontends (websocket fanout servers, TS clients, JSONL pipes) can
consume the event stream directly.

Additive only: no variant, field, or signature changes. serde floor
bumped to 1.0.186 for rename_all_fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review findings from PR #72:
- Normalize the five remaining snake_case payload fields to camelCase
  (usage.cacheRead/cacheWrite/totalTokens, errorMessage,
  providerMetadata) with serde aliases so pre-0.13 session files still
  load. The wire contract is now uniformly camelCase.
- Freeze tags via exhaustive match (no wildcard): a new AgentEvent or
  StreamDelta variant now fails to compile in the test file until its
  wire tag is pinned.
- Exact-JSON snapshot of a full messageEnd payload (all Content
  variants, non-default Usage, errorMessage) — freezes the nested shape
  that carries most wire bytes.
- Forward-compat tests: unknown fields ignored, unknown/wrong-case tags
  are clean Errs; legacy snake_case payload load test.
- Fix docs: MessageUpdate.message is a placeholder during streaming;
  clients accumulate deltas and resync at MessageEnd (the cumulative
  claim was false).
- serde floor corrected to 1.0.181 (actual rename_all_fields release).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yuanhao

yuanhao commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator Author

Applied review fixes from the two-agent pass:

  1. Nested payload casing decided now, not frozen by accidentusage.cacheRead/cacheWrite/totalTokens, errorMessage, providerMetadata normalized to camelCase (aliases keep pre-0.13 session files loadable). Wire format is now uniformly camelCase; documented in CHANGELOG incl. the one-way file-format note.
  2. Variant-addition guard — tag freezing now goes through an exhaustive match with no wildcard; a 13th variant fails to compile until its tag is pinned. StreamDelta's 3 tags frozen too.
  3. Full nested-shape snapshot — exact-JSON compare of a messageEnd with all 4 Content variants + non-default Usage + errorMessage.
  4. Forward-compat pinned — unknown fields ignored, unknown/wrong-cased tags → clean Err; legacy snake_case load test.
  5. False resync claim fixed — docs now say: accumulate from delta, resync at MessageEnd (MessageUpdate.message is a placeholder during streaming).
  6. serde floor → 1.0.181 (actual rename_all_fields release).

393 tests green, clippy -Dwarnings clean.

@yuanhao
yuanhao merged commit a18457f into main Jul 14, 2026
5 checks passed
@yuanhao
yuanhao deleted the feat/serialize-agent-events branch July 14, 2026 01:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant